package com.fuluwa.domain.usercenter.model.competence;

import java.util.Collections;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.ManyToOne;

import com.fuluwa.domain.security.model.User;
import com.fuluwa.domain.shared.AbstractIdDomainObject;
import com.fuluwa.infra.exception.PersistenceException;
import com.google.common.collect.Lists;

/**
 * define the user's competence score fore each.
 * 
 * @author yongxia
 * @Date Jul 13, 2013 10:32:57 PM
 */
@Entity
public class UserCompetenceScore extends AbstractIdDomainObject {
	@ManyToOne
	private User user;
	private float genericScore = 0;
	private float professionScore = 0;
	private float orgImpactScore = 0;
	private float handWorkingScore = 0;
	
//	@ManyToOne
//	private CareerLevelDefine careerLevelDefine;//FIXME the career level update

	private UserCompetenceScore() {
	}

	public UserCompetenceScore(User user) {
		this.user = user;
	}

	public User getUser() {
		return user;
	}

	public float getGenericScore() {
		return genericScore;
	}

	public float getProfessionScore() {
		return professionScore;
	}

	public float getOrgImpactScore() {
		return orgImpactScore;
	}

	public float getHandWorkingScore() {
		return handWorkingScore;
	}

	public void updateGenericScore(float genericScore) {
		this.genericScore = genericScore;
	}

	public void updateProfessionScore(float professionScore) {
		this.professionScore = professionScore;
	}

	public void updateOrgImpactScore(float orgImpactScore) {
		this.orgImpactScore = orgImpactScore;
	}

	public void updateHandWorkingScore(float handWorkingScore) {
		this.handWorkingScore = handWorkingScore;
	}

	public float getMinScore() {
		return getMin().getValue();
	}

	public CompetenceType getMinCompetenceType() {
		return getMin().getCompetenceType();
	}

	private TypeMapping getMin() {
		List<TypeMapping> list = Lists.newArrayListWithExpectedSize(4);
		list.add(new TypeMapping(CompetenceType.GENERIC, genericScore));
		list.add(new TypeMapping(CompetenceType.HAND_WORKING, handWorkingScore));
		list.add(new TypeMapping(CompetenceType.PROFESSION, professionScore));
		list.add(new TypeMapping(CompetenceType.ORG_IMPACT, orgImpactScore));
		Collections.sort(list);
		return list.get(0);
	}
	
	public void update(List<CompetenceSubDefine> subScores, LevelAdditionDefine levelAddtionDefine) throws PersistenceException {
		genericScore = compute(getSubDefines(subScores, CompetenceType.GENERIC), levelAddtionDefine);
		handWorkingScore = compute(getSubDefines(subScores, CompetenceType.HAND_WORKING), levelAddtionDefine);
		professionScore = compute(getSubDefines(subScores, CompetenceType.PROFESSION), levelAddtionDefine);
		orgImpactScore = compute(getSubDefines(subScores, CompetenceType.ORG_IMPACT), levelAddtionDefine);
		update();
	}
	

	private List<CompetenceSubDefine> getSubDefines(List<CompetenceSubDefine> subScores, CompetenceType tp) {
		List<CompetenceSubDefine> t=Lists.newArrayList();
		for (CompetenceSubDefine competenceSubDefine : subScores) {
			if(competenceSubDefine.getType().getCompetenceType().equals(tp)) {
				t.add(competenceSubDefine);
			}
		}
		return t;
	}

	private float compute(List<CompetenceSubDefine> subScores, LevelAdditionDefine levelAddtionDefine) {
		float ret = 0;
		if(subScores.size()<1)return ret;
		for (CompetenceSubDefine compSubDefineScore : subScores) {
			ret += compSubDefineScore.compute();
		}
		ret /= subScores.size();

		ret *= (levelAddtionDefine.getAddtion() + 1);
		return ret;
	}

	/*-	public static void main(String[] args) {
	 UserCompetenceScore s = new UserCompetenceScore(null);
	 s.updateGenericScore(1);
	 s.updateHandWorkingScore(2);
	 s.updateOrgImpactScore(3);
	 System.out.println(s.getMinScore().getCompetenceType());
	 System.out.println(s.getMinScore().getValue());
	 }*/

	private static class TypeMapping implements Comparable<TypeMapping> {
		private CompetenceType competenceType;
		private float value;

		public TypeMapping(CompetenceType competenceType, float value) {
			this.competenceType = competenceType;
			this.value = value;
		}

		@Override
		public int compareTo(TypeMapping o) {
			return (int) (value - o.getValue());
		}

		public CompetenceType getCompetenceType() {
			return competenceType;
		}

		public float getValue() {
			return value;
		}

	}

	@Override
	public String toString() {
		return "UserCompetenceScore [user=" + user + ", genericScore=" + genericScore + ", professionScore="
				+ professionScore + ", orgImpactScore=" + orgImpactScore + ", handWorkingScore=" + handWorkingScore
				+ "]";
	}

}
